<template>
  <div class="td-box" ref="can"></div>
</template>
<script setup>
import { onMounted, ref, onBeforeUnmount, computed, watch } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import editStore from "@/store/editStore";
import { getAssetsFile } from "@/utils/index.js";
import { debounce } from "@/utils";

let props = defineProps({
  from: {
    type: String,
    default: "",
  },
  storeJson: {
    type: Object,
    default: () => {},
  },
});

let frameId = null; //旋转动作id

const store = computed(() => {
  return props.from == "home" ? props.storeJson : editStore();
});

let can = ref();
let render = null;
let controls = null;
let camera = null;
let mesh = null;
let innerBox = null;
let currentInnerBox = null;

let scene = new THREE.Scene();

let loader = new THREE.TextureLoader();
loader.setCrossOrigin("Anonymous");

let AmbientLight = new THREE.AmbientLight("#fff", 1);
scene.add(AmbientLight);

function init() {
  innerBox = store.value.innerBox;
  currentInnerBox = store.value.innerBox.boxList[store.value.reelIndex];

  let geometry = new THREE.BoxGeometry(
    innerBox.boxLength,
    innerBox.boxHeigh,
    innerBox.boxWidth
  );

  let Material1 = new THREE.MeshBasicMaterial({
    color: "#904d15",
  });

  mesh = new THREE.Mesh(geometry, Material1);
  mesh.position.set(0, 0, 0);

  scene.add(mesh);

  currentInnerBox.leftComponentList.forEach((item) => {
    if (item.type == "Labels") {
      let x = -innerBox.boxLength / 2 - 3;
      let y = -item.x + innerBox.boxHeigh / 2 - item.length / 2;
      let z = item.y - innerBox.boxWidth / 2 + item.width / 2;
      let rx = ((item.angle + 90) / 180) * Math.PI;
      let ry = Math.PI / 2;
      let rz = 0;
      createPlaneGeometry(item, { x, y, z }, { rx, ry, rz });
    }
  });
  currentInnerBox.downComponentList.forEach((item) => {
    if (item.type == "Labels") {
      let x = item.x - innerBox.boxLength / 2 + item.length / 2;
      let y = -innerBox.boxHeigh / 2 - 3;
      let z = item.y - innerBox.boxWidth / 2 + item.width / 2;
      let rx = -Math.PI / 2;
      let ry = 0;
      let rz = -(item.angle / 180) * Math.PI;
      createPlaneGeometry(item, { x, y, z }, { rx, ry, rz });
    }
  });
  currentInnerBox.rightComponentList.forEach((item) => {
    if (item.type == "Labels") {
      let x = innerBox.boxLength / 2 + 3;
      let y = -item.x + innerBox.boxHeigh / 2 - item.length / 2;
      let z = item.y - innerBox.boxWidth / 2 + item.width / 2;
      let rx = -((item.angle + 90) / 180) * Math.PI;
      let ry = -Math.PI / 2;
      let rz = 0;
      createPlaneGeometry(item, { x, y, z }, { rx, ry, rz });
    }
  });
  currentInnerBox.upComponentList.forEach((item) => {
    if (item.type == "Labels") {
      let x = item.x - innerBox.boxLength / 2 + item.length / 2;
      let y = innerBox.boxHeigh / 2 + 3;
      let z = item.y - innerBox.boxWidth / 2 + item.width / 2;
      let rx = -Math.PI / 2;
      let ry = 0;
      let rz = -(item.angle / 180) * Math.PI;
      createPlaneGeometry(item, { x, y, z }, { rx, ry, rz });
    }
  });
  currentInnerBox.frontComponentList.forEach((item) => {
    if (item.type == "Labels") {
      let x = item.x - innerBox.boxLength / 2 + item.length / 2;
      let y = -item.y + innerBox.boxHeigh / 2 - item.width / 2;
      let z = innerBox.boxWidth / 2 + 3;
      let rx = 0;
      let ry = 0;
      let rz = -(item.angle / 180) * Math.PI;
      createPlaneGeometry(item, { x, y, z }, { rx, ry, rz });
    }
  });
  currentInnerBox.backComponentList.forEach((item) => {
    if (item.type == "Labels") {
      let x = item.x - innerBox.boxLength / 2 + item.length / 2;
      let y = -item.y + innerBox.boxHeigh / 2 - item.width / 2;
      let z = -innerBox.boxWidth / 2 - 3;
      let rx = 0;
      let ry = 0;
      let rz = -(item.angle / 180) * Math.PI;
      createPlaneGeometry(item, { x, y, z }, { rx, ry, rz });
    }
  });
}

init();

function createPlaneGeometry(item, position, rotation) {
  let label = new THREE.PlaneGeometry(item.length, item.width);
  let texture = loader.load(item.picName);
  let material = new THREE.MeshBasicMaterial({
    map: texture,
    side: THREE.DoubleSide,
  });
  let lmesh = new THREE.Mesh(label, material);

  lmesh.position.set(position.x, position.y, position.z);
  lmesh.rotation.set(rotation.rx, rotation.ry, rotation.rz);
  mesh.add(lmesh);
  if (item.qaStamp) {
    createCircleGeometry(item, lmesh);
  }
}

function createCircleGeometry(item, label) {
  let r = 10;
  let qa = new THREE.CircleGeometry(r);
  let texture = loader.load(getAssetsFile("QA"));
  let material = new THREE.MeshBasicMaterial({
    map: texture,
    side: THREE.DoubleSide,
  });
  let lmesh = new THREE.Mesh(qa, material);
  // lmesh.position.set(item.qaStampx + r, item.qaStampy - item.width + r, 1);
  lmesh.position.set(
    item.qaStampX - item.length / 2 + r,
    -item.qaStampY + item.width / 2 - r,
    1
  );
  lmesh.rotation.set(0, 0, (item.qaStampAngle / 180) * Math.PI);
  label.add(lmesh);
}

function action() {
  mesh.rotation.x += 0.001;
  mesh.rotation.y += 0.001;
  mesh.rotation.z += 0.001;
  render.render(scene, camera);
  frameId = requestAnimationFrame(action);
}

function resize() {
  render.setSize(can.value.offsetWidth, can.value.offsetHeight); // 根据缩放的窗口重新设置画布的大小
  // 垂直相机宽高比
  camera.aspect = can.value.offsetWidth / can.value.offsetHeight;
  // 更新相机投影矩阵
  camera.updateProjectionMatrix();
}
let debResize = debounce(resize, 100);

onMounted(() => {
  camera = new THREE.PerspectiveCamera(
    30,
    can.value.offsetWidth / can.value.offsetHeight,
    1,
    5000
  );
  camera.lookAt(0, 0, 0);
  camera.position.set(0, innerBox.boxLength * 4, 0);
  render = new THREE.WebGLRenderer({
    alpha: true,
    antialias: true,
  });
  render.setSize(can.value.offsetWidth, can.value.offsetHeight);
  render.setPixelRatio(window.devicePixelRatio);

  let controls = new OrbitControls(camera, render.domElement);
  controls.addEventListener("change", () => {
    render.render(scene, camera);
  });
  can.value.appendChild(render.domElement);
  if (props.from == "home") {
    action();
  } else {
    render.render(scene, camera);
  }
  window.addEventListener("resize", debResize);
});

onBeforeUnmount(() => {
  if (props.from == "home") {
    frameId && cancelAnimationFrame(frameId);
  }
  window.removeEventListener("resize", debResize);

  render.dispose();
  controls = null;
  render = null;
  camera = null;
  scene = null;
});

watch(
  () => props.storeJson,
  () => {
    scene.remove(mesh);
    mesh.geometry.dispose();
    init();
    render.render(scene, camera);
  }
);
</script>
<style scoped lang="scss">
.td-box {
  width: 100%;
  height: 100%;
}
</style>
